package com.zt.event.service.status.listener;

import cn.hutool.http.HttpUtil;
import com.zt.event.enums.ApplicationStatusEnums;
import com.zt.event.enums.MsgTypeEnums;
import com.zt.event.feishu.MessageInteractiveStatusDTO;
import com.zt.event.feishu.MessageNoticeDTO;
import com.zt.event.feishu.MessageTemplateEnum;
import okhttp3.MediaType;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.StringUtils;
import zt.digital.common.utils.DateUtil;
import zt.digital.common.utils.IpUtil;
import zt.digital.common.utils.JsonUtil;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.MessageFormat;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;


/**
 * @author system
 */
public abstract class DefaultListenerProcess implements ApplicationContextAware {

    public ApplicationContext context;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }

    String ACTIVE = "spring.profiles.active";
    String APPLICATION_NAME = "spring.application.name";

    String NOTICE_URL = "application.status.notice.url";

    String DEFAULT_NOTICE_URL = "https://open.feishu.cn/open-apis/bot/v2/hook/90c2ae33-6f21-4303-bec3-e69db90655e6";

    MediaType JSON = MediaType.get("application/json");

    String PLAIN_TEXT = "plain_text";
    String LARK_MD = "lark_md";
    String DIV = "div";

    public String defaultHandleMessage(ApplicationStatusEnums applicationStatus, String failureMessage, ApplicationContext applicationContext, long costTime) {
        String profileActive = applicationContext.getEnvironment().getProperty(ACTIVE);
        String applicationName = applicationContext.getEnvironment().getProperty(APPLICATION_NAME);
        String noticeUrl = applicationContext.getEnvironment().getProperty(NOTICE_URL);
        if (StringUtils.isEmpty(noticeUrl)) {
            noticeUrl = DEFAULT_NOTICE_URL;
        }
        MessageInteractiveStatusDTO messageInteractiveStatusDTO = new MessageInteractiveStatusDTO();
        messageInteractiveStatusDTO.setHeader(getHeader(applicationStatus.getMessageTemplateEnum(), MessageFormat.format("{0} 【{1}】服务 【{2}】环境" + "{3}", applicationStatus.getE(), applicationName == null ? "未知" : applicationName.toUpperCase(), profileActive == null ? "未知" : profileActive.toUpperCase(), applicationStatus.getValue())));
        messageInteractiveStatusDTO.setConfig(getConfig());
        MessageInteractiveStatusDTO.Title[][] template = getTemplate(profileActive, applicationName, IpUtil.getCurrentInstanceIp(), getCurrentInstanceHostName(), applicationStatus.getValue(),
                failureMessage, DateUtil.toString(DateUtil.toZone(DateUtil.getDateTime(),
                        ZoneId.of("Asia/Shanghai"))), costTime);
        List<MessageInteractiveStatusDTO.Elements> elements = new ArrayList<>();
        for (MessageInteractiveStatusDTO.Title[] title : template) {
            elements.add(getElement(title));
        }
        messageInteractiveStatusDTO.setElements(elements);
        MessageNoticeDTO<MessageInteractiveStatusDTO> messageNoticeDTO = new MessageNoticeDTO<>();
        messageNoticeDTO.setCard(messageInteractiveStatusDTO);
        messageNoticeDTO.setMsgType(MsgTypeEnums.INTERACTIVE.getKey());
        return sendMessage(noticeUrl, JsonUtil.toString(messageNoticeDTO));
    }

    public MessageInteractiveStatusDTO.Title[][] getTemplate(String profileActive, String applicationName,
                                                             String currentInstanceIp,
                                                             String currentInstanceHostName,
                                                             String status,
                                                             String failureMessage,
                                                             String requestTime,
                                                             long costTime) {
        return new MessageInteractiveStatusDTO.Title[][]{
                {new MessageInteractiveStatusDTO.Title(LARK_MD, MessageFormat.format("**应用环境：**\n{0}", profileActive)),
                        new MessageInteractiveStatusDTO.Title(LARK_MD, MessageFormat.format("**应用服务名：**\n{0}", applicationName))},
                {new MessageInteractiveStatusDTO.Title(LARK_MD, MessageFormat.format("**应用地址：**\n{0}", currentInstanceIp)),
                        new MessageInteractiveStatusDTO.Title(LARK_MD, MessageFormat.format("**应用主机：**\n{0}", currentInstanceHostName))},
                {new MessageInteractiveStatusDTO.Title(LARK_MD, MessageFormat.format("**服务状态：**\n{0}", status)),
                        new MessageInteractiveStatusDTO.Title(LARK_MD, MessageFormat.format("**请求时间：**\n{0}", requestTime))},
                {new MessageInteractiveStatusDTO.Title(LARK_MD, MessageFormat.format("**失败原因：**\n{0}", failureMessage)),
                        new MessageInteractiveStatusDTO.Title(LARK_MD, MessageFormat.format("**运行耗时：**\n{0}", costTime + "ms"))},
                {new MessageInteractiveStatusDTO.Title(LARK_MD, MessageFormat.format("**发布分支：**\n{0}", CommonEventPublishingRunListener.GIT_BRANCH_VALUE)),
                        new MessageInteractiveStatusDTO.Title(LARK_MD, MessageFormat.format("**构建时间：**\n{0}", CommonEventPublishingRunListener.GIT_BUILD_TIME_VALUE))},
                {new MessageInteractiveStatusDTO.Title(LARK_MD, MessageFormat.format("**最后提交时间：**\n{0}", CommonEventPublishingRunListener.GIT_COMMIT_TIME_VALUE)),
                        new MessageInteractiveStatusDTO.Title(LARK_MD, MessageFormat.format("**最后提交人邮箱：**\n{0}", CommonEventPublishingRunListener.GIT_COMMIT_USER_EMAIL_VALUE))},
                {new MessageInteractiveStatusDTO.Title(LARK_MD, MessageFormat.format("**最后提交人：**\n{0}", CommonEventPublishingRunListener.GIT_COMMIT_USER_NAME_VALUE))},
        };
    }


    public MessageInteractiveStatusDTO.Elements getElement(MessageInteractiveStatusDTO.Title[] titles) {
        MessageInteractiveStatusDTO.Elements elements = new MessageInteractiveStatusDTO.Elements();
        List<MessageInteractiveStatusDTO.Fields> fieldList = new ArrayList<>();
        for (MessageInteractiveStatusDTO.Title title : titles) {
            fieldList.add(getFields(title));
        }
        elements.setTag(DIV);
        elements.setFields(fieldList);
        return elements;
    }

    public MessageInteractiveStatusDTO.Fields getFields(MessageInteractiveStatusDTO.Title title) {
        MessageInteractiveStatusDTO.Fields fields = new MessageInteractiveStatusDTO.Fields();
        fields.setIsShort(Boolean.TRUE);
        fields.setText(getText(title.getTag(), title.getContent()));
        return fields;
    }

    public MessageInteractiveStatusDTO.Title getText(String tag, String content) {
        MessageInteractiveStatusDTO.Title title = new MessageInteractiveStatusDTO.Title();
        title.setTag(tag);
        title.setContent(content);
        return title;
    }

    public String getCurrentInstanceHostName() {
        InetAddress ip4 = null;
        try {
            ip4 = Inet4Address.getLocalHost();
        } catch (UnknownHostException e) {
            return null;
        }

        return ip4.getHostName();
    }


    public String sendMessage(String url, String dataJson) {
        return HttpUtil.post(url, dataJson);
    }

    public MessageInteractiveStatusDTO.Header getHeader(MessageTemplateEnum messageTemplateEnum, String content) {
        MessageInteractiveStatusDTO.Header header = new MessageInteractiveStatusDTO.Header();
        MessageInteractiveStatusDTO.Title title = new MessageInteractiveStatusDTO.Title();
        title.setContent(content);
        title.setTag(LARK_MD);
        header.setTemplate(messageTemplateEnum.getType());
        header.setTitle(title);
        return header;
    }

    public MessageInteractiveStatusDTO.Config getConfig() {
        MessageInteractiveStatusDTO.Config config = new MessageInteractiveStatusDTO.Config();
        config.setWideScreenMode(Boolean.TRUE);
        return config;
    }

}
